package br.com.android.games.daedal;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ContentUris;
import android.content.Context;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Color;
import android.graphics.Typeface;
import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.provider.ContactsContract;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.animation.Animation;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import br.com.android.games.daedal.flat.FlatBoard;
import br.com.games.daedal.Box;
import br.com.games.daedal.DaedalTeam;
import br.com.games.daedal.Vertex;
import br.com.games.daedal.ia.Ares;
import br.com.games.daedal.imp.DaedalPlayer;
import br.com.games.hefesto.Hefesto;
import br.com.games.hefesto.Move;
import br.com.games.hefesto.MoveListener;
import br.com.games.hefesto.Player;
import br.com.games.hefesto.board.Board;

public class DaedalDotsActivity extends Activity implements
		MoveListener<Vertex> {

	/**
	 * Sounds manager
	 */
	private Sounds sounds = new Sounds();

	private AndroDaedal game;

	/**
	 * Refresh screen
	 */
	public UpdateGame update = new UpdateGame();

	private boolean startNewGame = true;

	private List<Move<Vertex>> moves = new ArrayList<Move<Vertex>>();

	private Thread gamethread = null;

	public static final int REQUEST_CONNECT_DEVICE = 55;
	public static final int REQUEST_ENABLE_BT = 56;
	public static final int REQUEST_LISTEN_BT = 57;
	public static final int REMOTE_PLAYER_REQUEST = 58;
	public static final int PLAYER_PERFORM_MOVE = 59;
	public static final int START_NEW_GAME = 60;
	public static final int WAITING_REMOTE = 61;
	public static final int GAME_SERVER_UP = 62;
	public static final int REQUEST_PROGRESS_ON = 63;
	public static final int REQUEST_PROGRESS_OFF = 64;
	public static final int REQUEST_BEEP = 65;
	public static final int REQUEST_LOSE_MSG = 66;
	public static final int REQUEST_WIN_MSG = 67;
	public static final int REQUEST_PROGRESS = 68;
	public static final String IS_CLASSIC_MODE = "DaedalDotsActivity.isClassicMode";

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		/**
		 * Desligar o titulo da janela
		 */
		requestWindowFeature(Window.FEATURE_NO_TITLE);

		/**
		 * Ajustar para ser tela inteira
		 */
		getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
				WindowManager.LayoutParams.FLAG_FULLSCREEN);

		/**
		 * Ajustar esquema de volume
		 */
		setVolumeControlStream(AudioManager.STREAM_MUSIC);

		/**
		 * Ajustar LAYOUT Principal
		 */
		setContentView(R.layout.flat_board);

		Typeface font = Typeface.createFromAsset(getResources().getAssets(),
				"jrha.ttf");

		((TextView) findViewById(R.id.enemypoints)).setTypeface(font);
		((TextView) findViewById(R.id.playerpoints)).setTypeface(font);
		((TextView) findViewById(R.id.label_ur_turn)).setTypeface(font);
		
		boolean isClassic = getIntent().getBooleanExtra(IS_CLASSIC_MODE, true);

		((FlatBoard) findViewById(R.id.board2d)).setIsClassicMode(false);

		if (isClassic) {
			findViewById(R.id.main).setBackgroundResource(R.drawable.bg_single_player_classic);
		}

		getIntent().removeExtra(IS_CLASSIC_MODE);
		start(isClassic);
	}

	public void onNew(View v) {
		if (game.isGameOver()) {
			findViewById(R.id.bnt_exit).setEnabled(false);
			Animation ani = ChangeAnimation.outToLeftAnimation(getBoard());
			ani.setAnimationListener(new ChangeAnimation(getBoard()) {
				/*
				 * (non-Javadoc)
				 * 
				 * @see br.com.android.games.daedal.ChangeAnimation#
				 * onAnimationEnd(android.view.animation.Animation)
				 */
				@Override
				public void onAnimationEnd(Animation animation) {
					startNewGame = true;
					Animation ani = ChangeAnimation.inFromRightAnimation(getBoard());

					ani.setAnimationListener(new ChangeAnimation(getBoard()) {
						@Override
						public void onAnimationEnd(Animation animation) {
							update.sendEmptyMessage(REQUEST_PROGRESS);
							findViewById(R.id.bnt_exit).setEnabled(true);
						}
					});
				}
			});
		}

	}
	
	/**
	 * Usuário solicitou sair do jogo
	 * @param v
	 */
	public void onExit(View v) {
		onBackPressed();
	}

	/**
	 * Retonar ao lance anteriror
	 * @param v
	 */
	public void onUndo(View v) {

		if ((moves.size() > 0) && getBoard().isWaiting() && !game.isGameOver()) {

			findViewById(R.id.bnt_undo).setEnabled(false);

			Animation ani = ChangeAnimation.outToLeftAnimation(getBoard());
			ani.setAnimationListener(new ChangeAnimation(getBoard()) {
				/*
				 * (non-Javadoc)
				 * 
				 * @see br.com.android.games.daedal.ChangeAnimation#
				 * onAnimationEnd(android.view.animation.Animation)
				 */
				@Override
				public void onAnimationEnd(Animation animation) {
					int id = moves.size() - 1;

					while (id >= 0) {

						game.undo(moves.get(id));
						Move<Vertex> m = moves.remove(id);

						if (game.getCurrent().getTeam()
								.equals(DaedalTeam.WHITE)) {
							break;
						}

						id = moves.size() - 1;

						if (id < 0) {
							if (!game.getCurrent().getTeam()
									.equals(DaedalTeam.WHITE)) {
								game.perform(m);
								moves.add(m);
							}
						}
					}

					if (id > 0)
						getBoard().select(moves.get(id - 1).getMoveable(),
								Color.BLUE);

					Animation ani = ChangeAnimation
							.inFromRightAnimation(getBoard());

					ani.setAnimationListener(new ChangeAnimation(getBoard()) {
						@Override
						public void onAnimationEnd(Animation animation) {
							update.sendEmptyMessage(REQUEST_PROGRESS);
							findViewById(R.id.bnt_undo).setEnabled(true);
						}
					});
				};
			});
		}
	}

	private void start(boolean isClassic) {
		this.game = new AndroDaedal(this, new AndroPlayer(this,
				DaedalTeam.WHITE), isClassic ? new AndroPlayer(this,
						DaedalTeam.BLACK) : new Ares(DaedalTeam.BLACK, 5));
		Hefesto<Board<Box>, Vertex> hf = new Hefesto<Board<Box>, Vertex>(game);
		hf.addMoveListener(this);
		setInitialPlayer();
		this.gamethread = new Thread(hf);
		this.gamethread.start();
	}

	/**
	 * Ajustar o jogador confirme configuração
	 */
	private void setInitialPlayer() {
		SharedPreferences prefs = PreferenceManager
				.getDefaultSharedPreferences(this);

		if (prefs.getBoolean("whostart", false))
			game.setFirstTeam(DaedalTeam.BLACK);
		else
			game.setFirstTeam(DaedalTeam.WHITE);

		for (Player<?, ?> p : game.getPlayers()) {
			Ares a = (Ares) p;
			if (a.getTeam().equals(DaedalTeam.BLACK)) {
				String name = prefs.getString("aiPlayer", a.getName());
				String[] i = name.split(" ");
				if (i.length > 1)
					a.setLevel(Integer.valueOf(name.split(" ")[1]));
				a.setName(name);
			} else
				a.setName(prefs.getString("nickname", a.getName()));
		}

		String lookupkey = prefs.getString("lookupkey", "");

		if (lookupkey.length() > 1) {
			Bitmap pic = getContactImage(this, lookupkey);

			if (null != pic) {
				//ImageView you = (ImageView) findViewById(R.id.me);				
				//you.setImageBitmap(pic);
			}
		}

		setProgressBarOn(prefs.getBoolean("whostart", false));
	}


	public static Uri getContactLookupUri(String contactLookupKey) {
		return Uri.withAppendedPath(
				ContactsContract.Contacts.CONTENT_LOOKUP_URI, contactLookupKey);
	}

	public static Bitmap getContactImage(Context context,
			String contactLookupKey) {

		long contactId;

		try {
			Uri contactLookupUri = getContactLookupUri(contactLookupKey);
			Cursor c = context.getContentResolver().query(contactLookupUri,
					new String[] { ContactsContract.Contacts._ID }, null, null,
					null);
			try {
				if (c == null || c.moveToFirst() == false) {
					return null;
				}
				contactId = c.getLong(0);
			} finally {
				c.close();
			}

		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}

		Uri contactUri = ContentUris.withAppendedId(
				ContactsContract.Contacts.CONTENT_URI, contactId);
		InputStream input = ContactsContract.Contacts
				.openContactPhotoInputStream(context.getContentResolver(),
						contactUri);

		if (input != null) {
			return BitmapFactory.decodeStream(input);
		} else {
			return null;
		}
	}

	/**
	 * Recuperar o nome da conta google
	 * 
	 * @return
	 */
	public String getUsername() {
		AccountManager manager = AccountManager.get(this);
		Account[] accounts = manager.getAccountsByType("com.google");
		List<String> possibleEmails = new LinkedList<String>();

		for (Account account : accounts) {
			// TODO: Check possibleEmail against an email regex or treat
			// account.name as an email address only for certain account.type
			// values.
			possibleEmails.add(account.name);
		}

		if (!possibleEmails.isEmpty() && possibleEmails.get(0) != null) {
			String email = possibleEmails.get(0);
			String[] parts = email.split("@");
			if (parts.length > 0 && parts[0] != null)
				return parts[0];
			else
				return null;
		} else
			return null;
	}

	/**
	 * 
	 * @param value
	 */
	public void setProgressBarOn() {
		setProgressBarOn(game.getCurrent().getTeam().equals(DaedalTeam.BLACK));
	}

	/**
	 * 
	 * @param value
	 */
	private void setProgressBarOn(boolean value) {

		if (value) {
			findViewById(R.id.progressBar).setVisibility(ProgressBar.VISIBLE);
			findViewById(R.id.label_ur_turn).setVisibility(ProgressBar.INVISIBLE);
		} else {
			findViewById(R.id.progressBar).setVisibility(ProgressBar.INVISIBLE);
			findViewById(R.id.label_ur_turn).setVisibility(ProgressBar.VISIBLE);
			 
			if (game.getCurrent().getTeam().equals(DaedalTeam.BLACK))
			  ((TextView) findViewById(R.id.label_ur_turn)).setTextColor(getResources().getColor(R.color.gamer_red));
			else
			 ((TextView) findViewById(R.id.label_ur_turn)).setTextColor(getResources().getColor(R.color.gamer_green));
		}

		int wvalue = 0, bvalue = 0;

		for (Box b : game.getState().getSquares()) {
			if (b.getOwner().equals(DaedalTeam.WHITE))
				wvalue += b.getValue();

			if (b.getOwner().equals(DaedalTeam.BLACK))
				bvalue += b.getValue();
		}

		((TextView) findViewById(R.id.playerpoints)).setText(String.format("%d", wvalue));
		((TextView) findViewById(R.id.enemypoints)).setText(String.format("%d",	bvalue));

		getBoard().waitMove(!value);
	}

	/**
	 * Refresh screen
	 * 
	 * @author schindler
	 */
	public class UpdateGame extends Handler {
		/*
		 * (non-Javadoc)
		 * 
		 * @see android.os.Handler#handleMessage(android.os.Message)
		 */
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);

			try {

				switch (msg.what) {
				case REQUEST_BEEP:
					sounds.sound(DaedalDotsActivity.this, R.raw.metal);
					break;
				case REQUEST_PROGRESS_ON:
					setProgressBarOn(true);
					break;
				case REQUEST_PROGRESS_OFF:
					setProgressBarOn(false);
					break;
				case REQUEST_PROGRESS:
					setProgressBarOn();
					break;
				case REQUEST_WIN_MSG: {
					DaedalPlayer p = (DaedalPlayer) msg.obj;

					if (p.getTeam().equals(DaedalTeam.WHITE)) {
						Toast.makeText(
								DaedalDotsActivity.this,
								getString(R.string.app_show_winner,
										p.getName(), msg.arg1, msg.arg2),
								Toast.LENGTH_LONG).show();
						sounds.sound(DaedalDotsActivity.this, R.raw.applause);
					} else {
						Toast.makeText(
								DaedalDotsActivity.this,
								getString(R.string.app_show_loser, msg.arg1,
										msg.arg2), Toast.LENGTH_LONG).show();
						sounds.sound(DaedalDotsActivity.this, R.raw.wrong);
					}
					setProgressBarOn(false);
					break;
				}
				case PLAYER_PERFORM_MOVE:
					FlatBoard vBoard = (FlatBoard) findViewById(R.id.board2d);
					vBoard.select((Vertex) msg.obj, Color.BLUE);
					sounds.sound(DaedalDotsActivity.this, R.raw.move);
					setProgressBarOn();
					break;
				case START_NEW_GAME:
					moves.clear();
					setInitialPlayer();
					break;
				}
				getBoard().postInvalidate();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see android.app.Activity#onBackPressed()
	 */
	@Override
	public void onBackPressed() {
		new AlertDialog.Builder(this)
				.setIcon(android.R.drawable.ic_dialog_alert)
				.setTitle(R.string.app_name)
				.setMessage(R.string.app_on_exit)
				.setPositiveButton(android.R.string.yes,
						new DialogInterface.OnClickListener() {
							@Override
							public void onClick(DialogInterface dialog,
									int which) {
								finish();
							}

						}).setNegativeButton(android.R.string.no, null).show();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see br.com.games.hefesto.MoveListener#onMove(br.com.games.hefesto.Move,
	 * br.com.games.hefesto.Player)
	 */
	@Override
	public void onMove(Move<Vertex> move, Player<?, Vertex> player) {
		Message msg = new Message();
		msg.what = PLAYER_PERFORM_MOVE;
		msg.obj = move.getMoveable();
		update.sendMessage(msg);
		this.moves.add(new Move<Vertex>(move.getMoveable()));

		try {
			Thread.sleep(500);
		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	public FlatBoard getBoard() {
		return (FlatBoard) findViewById(R.id.board2d);
	}

	public boolean isStartNewGame() {
		return startNewGame;
	}

	public void setStartNewGame(boolean startNewGame) {
		this.startNewGame = startNewGame;
	}
}